package com.jketing.spring.mvc.filter;

import java.io.IOException;
import java.util.Locale;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 	ForwordHttpMethodFilter 转发http请求方法过滤器
 * 
 * 	功能：REST风格的URL提交的PUT和DELETE请求进行转发时 
 * 		浏览器报错  HTTP Status [405] – [Method Not Allowed] JSPs only permit GET POST or HEAD
 * 		意思是浏览器只支持GET POST or HEAD不支持PUT和DELETE
 * 		此过滤器是在Servlet进行Forword时将PUT和DELETE请求再转为POST请求，是HiddenHttpMethodFilter的逆过程
 * 	
 * 	备注：为实现从list页进入编辑页，在update提交数据保存返回list时能回到原来查询条件和排序的分页，重定向只能返回到第一页,故
 * 		需要在PUT请求后进行Forword转发操作而不是重定向
 * 	
 * 
 * 	@author  李荣华
 * 	@version v1.0
 * 	@date    2017-11-4
 * 	@since   Spring-mvc 4.3.8
 */
public class ForwordHttpMethodFilter extends OncePerRequestFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		HttpServletRequest requestToUse = request;

		if ("PUT".equals(request.getMethod()) || "DELETE".equals(request.getMethod())) {
			requestToUse = new HttpMethodRequestWrapper(request, "POST");//将PUT和DELETE两种请求再转化回原来的POST请求
		}
		filterChain.doFilter(requestToUse, response);
	}


	/**
	 * Simple {@link HttpServletRequest} wrapper that returns the supplied method for
	 * {@link HttpServletRequest#getMethod()}.
	 */
	private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {

		private final String method;

		public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
			super(request);
			this.method = method.toUpperCase(Locale.ENGLISH);
		}

		@Override
		public String getMethod() {
			return this.method;
		}
	}

}
